#include "ct_config.h"
#include "ct_gpio.h"
/*****************************************************************************
 * Private Functions
 ****************************************************************************/

/*****************************************************************************
 * Public Functions
 ****************************************************************************/

// void ct_gpio_Init(void ) {

//
//}
/****************************************************************************/

void ct_gpio_SetMode(ct_gpio_port_t portx,
                     uint8_t        PinMask,
                     ct_gpio_mode_t mode) {
    uint8_t u8PnM1, u8PnM2;
    // if ((portx > CT_GPIO_PORT3) && (portx == CT_GPIO_PORT2)) return;
    switch (portx) {
        case CT_GPIO_PORT0:
            u8PnM1 = P0M1;
            u8PnM2 = P0M2;
            break;
#ifdef CT_USE_PORT1
        case CT_GPIO_PORT1:
            u8PnM1 = P1M1;
            u8PnM2 = P1M2;
            break;
#endif
#ifdef CT_USE_PORT2
        case CT_GPIO_PORT2:
            u8PnM1 = P2M1;
            u8PnM2 = P2M2;
            break;
#endif
#ifdef CT_USE_PORT3
        case CT_GPIO_PORT3:
            u8PnM1 = P3M1;
            u8PnM2 = P3M2;
            break;
#endif
#ifdef CT_USE_PORT4
        case CT_GPIO_PORT4:
            u8PnM1 = P4M1;
            u8PnM2 = P4M2;
            break;
#endif
#ifdef CT_USE_PORT5
        case CT_GPIO_PORT5:
            u8PnM1 = P5M1;
            u8PnM2 = P5M2;
            break;
#endif
        // Add other ports here...
        default:
            break;
    }

    switch (mode) {
        case CT_GPIO_MODE_INPUT:
            u8PnM1 |= PinMask;
            u8PnM2 &= ~PinMask;
            break;
        case CT_GPIO_MODE_OUT_PP:
            u8PnM1 &= ~PinMask;
            u8PnM2 |= PinMask;
            break;
        case CT_GPIO_MODE_QUASI:
            u8PnM1 &= ~PinMask;
            u8PnM2 &= ~PinMask;
            break;
        case CT_GPIO_MODE_OUT_OD:
            u8PnM1 |= PinMask;
            u8PnM2 |= PinMask;
            break;
        default:
            break;
    }

    switch (portx) {
        case CT_GPIO_PORT0:
            P0M1 = u8PnM1;
            P0M2 = u8PnM2;
            break;
        case CT_GPIO_PORT1:
            P1M1 = u8PnM1;
            P1M2 = u8PnM2;
            break;
#ifdef CT_USE_PORT2
        case CT_GPIO_PORT2:
            P2M1 = u8PnM1;
            P2M2 = u8PnM2;
            break;
#endif
#ifdef CT_USE_PORT3
        case CT_GPIO_PORT3:
            P3M1 = u8PnM1;
            P3M2 = u8PnM2;
            break;
#endif
#ifdef CT_USE_PORT4
        case CT_GPIO_PORT4:
            P4M1 = u8PnM1;
            P4M2 = u8PnM2;
            break;
#endif
#ifdef CT_USE_PORT5
        case CT_GPIO_PORT5:
            P5M1 = u8PnM1;
            P5M2 = u8PnM2;
            break;
#endif
            // Add other ports here...
        default:
            break;
    }
}

/****************************************************************************/
ct_gpio_sta_t ct_gpio_ReadPin(ct_gpio_port_t portx, uint8_t PinMask) {
    switch (portx) {
        case CT_GPIO_PORT0:
            return (P0 & PinMask) ? CT_GPIO_HIGH : CT_GPIO_LOW;

        case CT_GPIO_PORT1:
            return (P1 & PinMask) ? CT_GPIO_HIGH : CT_GPIO_LOW;
#ifdef CT_USE_PORT2
        case CT_GPIO_PORT2:
            return (P2 & PinMask) ? CT_GPIO_HIGH : CT_GPIO_LOW;
#endif
#ifdef CT_USE_PORT3
        case CT_GPIO_PORT3:
            return (P3 & PinMask) ? CT_GPIO_HIGH : CT_GPIO_LOW;
#endif
#ifdef CT_USE_PORT4
        case CT_GPIO_PORT4:
            return (P4 & PinMask) ? CT_GPIO_HIGH : CT_GPIO_LOW;
#endif
#ifdef CT_USE_PORT5
        case CT_GPIO_PORT5:
            return (P5 & PinMask) ? CT_GPIO_HIGH : CT_GPIO_LOW;
#endif
        default:
            return CT_GPIO_HIGH;
    }
}

/****************************************************************************/
void ct_gpio_WritePin(ct_gpio_port_t portx,
                      uint8_t        PinMask,
                      ct_gpio_sta_t  state) {
    SFRS = 0;
    switch (portx) {
        case CT_GPIO_PORT0:
            if (state == CT_GPIO_LOW) {
                P0 &= ~(PinMask);
            } else if (state == CT_GPIO_HIGH) {
                P0 |= PinMask;
            } else if (state == CT_GPIO_TOG) {
                P0 ^= PinMask;
            }
            break;

        case CT_GPIO_PORT1:
            if (state == CT_GPIO_LOW) {
                P1 &= ~(PinMask);
            } else if (state == CT_GPIO_HIGH) {
                P1 |= PinMask;
            } else if (state == CT_GPIO_TOG) {
                P1 ^= PinMask;
            }
            break;
#ifdef CT_USE_PORT2
        case CT_GPIO_PORT2:
            if (state == CT_GPIO_LOW) {
                P2 &= ~(PinMask);
            } else if (state == CT_GPIO_HIGH) {
                P2 |= PinMask;
            } else if (state == CT_GPIO_TOG) {
                P2 ^= PinMask;
            }
            break;
#endif
#ifdef CT_USE_PORT3
        case CT_GPIO_PORT3:
            if (state == CT_GPIO_LOW) {
                P3 &= ~(PinMask);
            } else if (state == CT_GPIO_HIGH) {
                P3 |= PinMask;
            } else if (state == CT_GPIO_TOG) {
                P3 ^= PinMask;
            }
            break;
#endif
#ifdef CT_USE_PORT4
        case CT_GPIO_PORT4:
            if (state == CT_GPIO_LOW) {
                P4 &= ~(PinMask);
            } else if (state == CT_GPIO_HIGH) {
                P4 |= PinMask;
            } else if (state == CT_GPIO_TOG) {
                P4 ^= PinMask;
            }
            break;
#endif
#ifdef CT_USE_PORT5
        case CT_GPIO_PORT5:
            if (state == CT_GPIO_LOW) {
                P5 &= ~(PinMask);
            } else if (state == CT_GPIO_HIGH) {
                P5 |= PinMask;
            } else if (state == CT_GPIO_TOG) {
                P5 ^= PinMask;
            }
            break;
#endif
            // Add other ports here...
        default:
            break;
    }
}
/****************************************************************************/
void ct_gpio_TogglePin(ct_gpio_port_t portx, uint8_t PinMask) {
    SFRS = 0;
    switch (portx) {
        case CT_GPIO_PORT0:
            P0 ^= PinMask;
            break;

        case CT_GPIO_PORT1:
            P1 ^= PinMask;
            break;
#ifdef CT_USE_PORT2
        case CT_GPIO_PORT2:
            P2 ^= PinMask;
            break;
#endif
#ifdef CT_USE_PORT3
        case CT_GPIO_PORT3:
            P3 ^= PinMask;
            break;
#endif
#ifdef CT_USE_PORT4
        case CT_GPIO_PORT4:
            P4 ^= PinMask;
            break;
#endif
#ifdef CT_USE_PORT5
        case CT_GPIO_PORT5:
            P5 ^= PinMask;
            break;
#endif
        // Add other ports here...
        default:
            break;
    }
}

/****************************************************************************/
void ct_gpio_ExInt_Enable(ct_gpio_Int_t           channel,
                          ct_gpio_irq_trip_mode_t mode,
                          ct_bool                 enable) {
    switch (channel) {
        case CT_INT0:
            switch (mode) {
                case LEVEL:
                    clr_TCON_IT0;
                    break;
                case EDGE:
                    set_TCON_IT0;
                    break;
            }
            switch (enable) {
                case DISABLE:
                    clr_IE_EX0;
                    break;
                case ENABLE:
                    set_IE_EX0;
                    break;
            }
            break;

        case CT_INT1:
            switch (mode) {
                case LEVEL:
                    clr_TCON_IT0;
                    break;
                case EDGE:
                    set_TCON_IT0;
                    break;
            }
            switch (enable) {
                case DISABLE:
                    clr_IE_EX1;
                    break;
                case ENABLE:
                    set_IE_EX1;
                    break;
            }
            break;
        default:
            break;
    }
}
/****************************************************************************/

static void set_irq_trigger_mode(uint8_t            PinMask,
                                 ct_gpio_irq_trip_t trip) {
    switch (trip) {
        case CT_GPIO_IRQ_LOW_LEVEL:
            PICON &= ~PinMask;
            PINEN |= PinMask;
            PIPEN &= ~PinMask;
            break;
        case CT_GPIO_IRQ_HIGH_LEVEL:
            PICON &= ~PinMask;
            PINEN &= ~PinMask;
            PIPEN |= PinMask;
            break;
        case CT_GPIO_IRQ_FALLING_EDGE:
            PICON |= PinMask;
            PINEN |= PinMask;
            PIPEN &= ~PinMask;
            break;
        case CT_GPIO_IRQ_RISING_EDGE:
            PICON |= PinMask;
            PINEN &= ~PinMask;
            PIPEN |= PinMask;
            break;
        case CT_GPIO_IRQ_BOTH_EDGE:
            PICON |= PinMask;
            PINEN |= PinMask;
            PIPEN |= PinMask;
            break;
        default:
            break;
    }
}

/****************************************************************************/
void ct_gpio_irq_Enable(ct_gpio_port_t     portx,
                        uint8_t            PinMask,
                        ct_gpio_irq_trip_t trip) {

    switch (portx) {
        case CT_GPIO_PORT0:
            ENABLE_INT_PORT0;
            break;
        case CT_GPIO_PORT1:
            ENABLE_INT_PORT1;
            break;
#ifdef CT_USE_PORT2
        case CT_GPIO_PORT2:
            ENABLE_INT_PORT2;
            break;
#endif
#ifdef CT_USE_PORT3
        case CT_GPIO_PORT3:
            ENABLE_INT_PORT3;
            break;
#endif
#ifdef CT_USE_PORT4
        case CT_GPIO_PORT4:
            ENABLE_INT_PORT4;
            break;
#endif
#ifdef CT_USE_PORT5
        case CT_GPIO_PORT5:
            ENABLE_INT_PORT5;
            break;
#endif
        default:
            break;
    }

    set_irq_trigger_mode(PinMask, trip);
}

/****************************************************************************/
void ct_gpio_SchmittTrigger(ct_gpio_port_t    portx,
                            uint8_t           PinMask,
                            ct_gpio_Schmitt_t state) {
    ENABLE_SFR_PAGE1;
    switch (portx) {
        case CT_GPIO_PORT0:
            if (state) {
                P0S |= PinMask;
            } else {
                P0S &= ~PinMask;
            }
            break;
        case CT_GPIO_PORT1:
            if (state) {
                P1S |= PinMask;
            } else {
                P1S &= ~PinMask;
            }
            break;
#ifdef CT_USE_PORT2
        case CT_GPIO_PORT2:
            if (state) {
                P2S |= PinMask;
            } else {
                P2S &= ~PinMask;
            }
            break;
#endif
#ifdef CT_USE_PORT3
        case CT_GPIO_PORT3:
            if (state) {
                P3S |= PinMask;
            } else {
                P3S &= ~PinMask;
            }
            break;
#endif
#ifdef CT_USE_PORT4
        case CT_GPIO_PORT4:
            if (state) {
                P4S |= PinMask;
            } else {
                P4S &= ~PinMask;
            }
            break;
#endif
#ifdef CT_USE_PORT5
        case CT_GPIO_PORT5:
            if (state) {
                P5S |= PinMask;
            } else {
                P5S &= ~PinMask;
            }
            break;
#endif
        default:
            break;
    }
    ENABLE_SFR_PAGE0;
}
/****************************************************************************/
#if 0
/**
 * @brief Set the specified GPIO port and pin as quasi-bidirectional mode.
 * @param[in] portx GPIO port
 * @param[in]  PinMask GPIO pin
 * @return No return value
 */
void ct_gpio_SetQuasi(ct_gpio_port_t portx, uint8_t PinMask) {
    ct_gpio_SetMode(portx, PinMask, CT_GPIO_MODE_QUASI);
}

/**
 * @brief Set the specified GPIO port and pin as input mode.
 * @param[in] portx GPIO port
 * @param[in]  PinMask GPIO pin
 * @return No return value
 */
void ct_gpio_SetInput(ct_gpio_port_t portx, uint8_t PinMask) {
    ct_gpio_SetMode(portx, PinMask, CT_GPIO_MODE_INPUT);
}

/**
 * @brief Set the specified GPIO port and pin as output mode.
 * @param[in] portx GPIO port
 * @param[in]  PinMask GPIO pin
 * @return No return value
 */
void ct_gpio_SetOutput(ct_gpio_port_t portx, uint8_t PinMask) {
    ct_gpio_SetMode(portx, PinMask, CT_GPIO_MODE_OUT_PP);
}

/**
 * @brief Set the specified GPIO port and pin as open drain mode.
 * @param[in] portx GPIO port
 * @param[in]  PinMask GPIO pin
 * @return No return value
 */
void ct_gpio_SetOpenDrain(ct_gpio_port_t portx, uint8_t PinMask) {
    ct_gpio_SetMode(portx, PinMask, CT_GPIO_MODE_OUT_OD);
}


/**
 * @brief GPIO Pull up enable setting
 * @param[in] portx GPIO port
 * @param[in]  PinMask GPIO pin
 * @return No return value
 */
void ct_gpio_PullUp_Enable(ct_gpio_port_t portx, uint8_t PinMask) {
    (void)portx;
    (void)PinMask;
}

/**
 * @brief GPIO Pull up disable setting
 * @param[in] portx GPIO port
 * @param[in]  PinMask GPIO pin
 * @return No return value
 */
void ct_gpio_PullUp_Disable(ct_gpio_port_t portx, uint8_t PinMask) {
    (void)portx;
    (void)PinMask;
}

/**
 * @brief GPIO Pull down enable setting
 * @param[in] portx GPIO port
 * @param[in]  PinMask GPIO pin
 * @return No return value
 */
void ct_gpio_PullDown_Enable(ct_gpio_port_t portx, uint8_t PinMask) {
    (void)portx;
    (void)PinMask;
}


/**
 * @brief GPIO Pull down disable setting
 * @param[in] portx GPIO port
 * @param[in]  PinMask GPIO pin
 * @return No return value
 */
void ct_gpio_PullDown_Disable(ct_gpio_port_t portx, uint8_t PinMask) {
    (void)portx;
    (void)PinMask;
}

#endif
